package org.carpediem.conman.rest;

import com.sun.jersey.multipart.BodyPart;
import com.sun.jersey.multipart.BodyPartEntity;
import com.sun.jersey.multipart.MultiPart;
import org.apache.commons.io.IOUtils;
import org.carpediem.conman.api.ConMan;
import org.carpediem.conman.entity.*;
import org.carpediem.schema.conman.ContactInfo;
import org.carpediem.schema.conman.NoteInfo;

import javax.servlet.ServletContext;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.logging.Logger;

/**
 * @author Mark Petrovic
 */
@Path("/contacts/{contactId: [0-9]+}")
final public class ContactResource extends AbstractResource {
    private final static Logger logger = Logger.getLogger(ContactResource.class.getName());

    public ContactResource(@Context UriInfo uriInfo, @Context ServletContext servletContext) {
        super(uriInfo, servletContext);
    }

    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Contact getContact(@PathParam("contactId") long contactId) {
        requireContactExists(contactId);
        return contactDao.get(contactId);
    }

    @Path("documents")
    @GET
    @Produces(MediaType.APPLICATION_XML)
    public DocumentBag getDocuments(@PathParam("contactId") long contactId) {
        Contact contact = requireContactExists(contactId);
        List<Document> documents = documentDao.getByOwner(contact);
        return entityToBag(documents, DocumentBag.class);
    }

    @Path("documents")
    @POST
    @Consumes(ConMan.MULTIPART_MIXED)
    @Produces(MediaType.APPLICATION_XML)
    public Document addAttachment(@PathParam("contactId") long contactId, MultiPart multiPart) throws IOException {
        Contact contact = requireContactExists(contactId);
        requireMultiParts(multiPart);

        List<BodyPart> bodyParts = multiPart.getBodyParts();
        ContactInfo cInfo = bodyParts.get(0).getEntityAs(ContactInfo.class);
        logger.info(toXml(cInfo));

        // Todo:  bounds check
        BodyPartEntity bpe = (BodyPartEntity) bodyParts.get(1).getEntity();
        InputStream stream = bpe.getInputStream();
        byte[] docBuffer = IOUtils.toByteArray(stream);

        requireDocumentNotBound(contact, docBuffer);

        return documentDao.add(contact, cInfo, docBuffer);
    }

    @Path("documents/{documentId: [0-9]+}")
    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Document getDocument(@PathParam("contactId") long contactId, @PathParam("documentId") long documentId) {
        Contact contact = requireContactExists(contactId);
        Document document = requireDocumentExists(documentId);
        requireContactOwnsDocument(contact, document);

        return document;
    }

    @Path("notes")
    @GET
    @Produces(MediaType.APPLICATION_XML)
    public NoteBag getNotes(@PathParam("contactId") long contactId) {
        Contact contact = requireContactExists(contactId);
        List<Note> notes = noteDao.getByOwner(contact);
        return entityToBag(notes, NoteBag.class);
    }

    @Path("notes")
    @POST
    @Consumes(MediaType.APPLICATION_XML)
    @Produces(MediaType.APPLICATION_XML)
    public Note addNote(@PathParam("contactId") long contactId, JAXBElement<NoteInfo> request) throws IOException {
        Contact contact = requireContactExists(contactId);
        NoteInfo nInfo = request.getValue();
        logger.info(toXml(nInfo));

        return noteDao.add(contact, nInfo);
    }

    @Path("notes/{noteId: [0-9]+}")
    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Note getNote(@PathParam("contactId") long contactId, @PathParam("noteId") long noteId) {
        Contact contact = requireContactExists(contactId);
        Note note = requireNoteExists(noteId);
        requireContactOwnsNote(contact, note);

        return note;
    }


}
